home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CICA Windows Explosion!
/
The CICA Windows Explosion! - Disc 2.iso
/
winsock
/
ircii2-6.zip
/
SRC\IRCII-2.6\SCRIPT\COMPL.MOD
< prev
next >
Wrap
Text File
|
1994-12-28
|
13KB
|
350 lines
# Complete Modules by Ian Frechette
# Last updated 2-2-94
# example modules
# Don't let the size scare you. This is a whole collection of
# examples and comments about the design of modules
# meat of all this are the interface functions to 'complete'
# compl.add, and compl.list (soon to be compl.del)
# the function that does the work is compl.parse which is very small
# and whatever parsing routine it calls.
# These should actually all be in their individual modules
# but this is just an example file..
# Note.. compl.list is internal to complete.. shoulnd't normally be used
if (compl.list == [])
{
# Note here.. Currently, if you compl.add /blah blahparse
# followed by compl.add /blah otherparse only the latter will
# called. No conflict message is shown unless you replace the
# default 'null' and 'nomatch' parsers.
compl.add -null -nomatch /m messparse
compl.add /msg messparse
compl.add /connect connparse
compl.add /tr connparse
compl.add /load loadparse
compl.add /test testparse
compl.add /con expand.con
compl.add /conbunch expand.con
}
# message parser module.. Compatible with included tabscript
# currently calls the tabkey script under 3 conditions
# the input line has more than 2 argments on it.. '/msg bob thud<TAB>'
# the input line has nothing on it '<TAB>'
# the input line has only one argument and the character before the
# cursor is a space '/msg bob <TAB>'
# plus it now does nickname completion
# /m D<TAB> expands to /m Daemon and so on
alias messparse {
if (([$1] != []) && ([$2] == []))
{
if (right(1 $*) != [ ])
{
# this is the simple match.. just match first occurance
# and expand
if (mp.cnt = match($(1)* $tk.msglist))
{
parsekey delete_previous_word
# in case one does /m =ni<TAB> it must delete the =
if (index(#=% $1) >= 0) {parsekey backspace}
type $word(${mp.cnt - 1} $tk.msglist)
type ${[ ]}
}
}
{
^tk.getmsg 1 $tk.msglist
}
}
{
^tk.getmsg 1 $tk.msglist
}
}
# connect module for opers.. easily changeable to kicks, bans.. etc..
# simply use /connect <TAB> for list or /connect <uniqid tag><TAB>
# eg. /connect pen<TAB> expands to /connect penfold.ece.uiuc.edu
# It always expands first matching string. Look at testparse for
# a more intelligent way to do it.
@ connlist = [irc.uiuc.edu goren1.u.washington.edu ircserver.iastate.edu w6yx.stanford.edu hamblin.math.byu.edu freedom.nmsu.edu dreamtime.unm.edu ircserver.santafe.edu irc.netsys.com irc-2.mit.edu cs-mail.bu.edu]
alias connparse {
if ([$1] != [])
{
@ cp.line = [$*]
if ((right(1 $*) == [ ]) && ([$2] == [])&& ([$0] == [/connect]))
{
type 6667;type ${[ ]}
# note.. if converted to use smartparse.. the port number must
# be removed here.. the above logic conflicts with SP
}
{
# expand only the first match found (See 'testparse' for better way
if (cp.cnt = match($(${#cp.line -1})* $connlist))
{
delword
type $word(${cp.cnt - 1} $connlist)
type ${[ ]}
}
{
echo *** connlist $connlist
}
}
}
{
echo *** connlist $connlist
}
}
# Load module
# /load net<TAB> expand to /load netsplit and so on.
# Note the problem right now is that it only finds and expands the first
# name in the list I think we can get around this.
@ loadlist = [netsplit ircgrep cut-paste compl.mods]
alias loadparse {
if ([$1] != []) {
if (lp.cnt = match($(1)* $loadlist))
{
parsekey delete_previous_word
type $word(${lp.cnt - 1} $loadlist)
}
}
{
echo *** loadlist = $loadlist
}
^assign -lp.cnt
}
# ############ stuff related to SMARTPARSE ###################
# The new testparse rewritten to use the
# extremely awsome smartparse routine.
if (!match(/test $compl.list)) {compl.add /test testparse}
# just a quick alias for making LINKS lists.. /makelist testlist *.edu
# will make a list of all *.edu servers.. Note that just * is
# generally too big a list for ircII
alias makelist {
if ([$1])
{
^on ^364 * push $0 $$1
links $1-
wait -cmd eval ^on 364 -\;echo *** makelist finished
}
}
@ testlist = [aone atwo athree bone btwo bthree ircserver.iastate.edu ircserver.santafe.edu]
# testparse <cmd> <stuff....pat>
# this is called by the complete routines.
@ tp.tmp = [0 :]
# [0 :] represents a count of 0.. and a null pattern :<pat>
alias testparse {
# ignore this first line..
@ tp.cnt = [$*]
@ tp.cnt = #tp.cnt
^assign -tp.pat
# all the cnt stuff is in case you do /command word1 word2 pattern<tab>
if (tp.cnt > 1)
{
@ tp.pat = [$(${tp.cnt - 1})]
# '/command pattern ' leaves <pat> null
# '/command pattern' sets <pat> to a new pattern
# important because smartparse may leave a space
if (right(1 $L) != [ ]) {@ tp.tmp = [0 :$tp.pat]}
# Uncomment the following line to see how it works from here.. debugging
# echo smartparse\($tp.tmp testlist $tp.pat\)
# call testparse with current cnt :<pat> <listname> <newpat>
@ tp.tmp = smartparse($tp.tmp testlist $tp.pat)
# note tp.tmp accounts for two arguments.. and is modified and saved
if (left(1 $word(1 $tp.tmp)) == [,])
{echo *** no match for pattern [$tp.pat] found in list}
{if (left(1 $word(1 $tp.tmp)) == [.])
{echo *** testlist: $testlist}}
}
{
echo *** testlist : $testlist
}
}
alias test echo *** TEST: You've matched: $*
# test module
# Trying to make some sort of intelligent handling of the tab lists.
@ sp.cnt = 0
# call it with smartparse <cnt> :<pat> <listname> <newpat>
# $0 $1 $2 $3
# returns <counter> [:,.]<pattern>
# : == successful match , == no match . == null
#
# Look at how testparse uses it.. you shouldn't have to touch any
# smartparse vars.. It's all handled through the interface.. basically
# you're telling it where to start looking in the list and how
# long the list is.. Each time smartparse is called it returns a counter
# value indicating where it left off last time. You can save it
# or not.. testparse saves it.. and passes it back as the new
# starting position <cnt>
#
# Assuming the counter, pattern, and list are maintained through each call
# it'll assume you're searching forward in the list from some place
# after the last word matched in the list..
#
# If you feed it a <newpat> for which <pat> is not a subset, it'll reassign
# <pat> to <newpat> and restart the process..
# It defaults to expansion.. so.. <pat> = blah
# will match blahone, blahtwo etc. Works with wildcards.. *a* matches a lot
# Try it.
^assign -sp.tmp
alias smartparse {
# int sp.tmp - index of last match found
# int sp.cnt - position in list
# int sp.max - max number of elements in list
# string sp.pat - match pattern
if ([$3] != [])
{
# Extract <pat> from :<pat> Note.. It may be null
@ sp.pat = mid(1 50 $1)
@ sp.max = [$(#$2)]
@ sp.cnt = [$0]
# set pattern. Determine if we've changed the base pattern or not
if (sp.pat == [])
{@ sp.pat = [$3]}
{ if (!match($(sp.pat)* $3)) {@sp.pat = [$3]} }
@ sp.run = 1
while (((sp.list = words($sp.cnt $sp.max $($2))) != []) && (!sp.tmp) && sp.run)
{
# look for match in list
if (sp.tmp = match($(sp.pat)* $sp.list))
{
# sp.cnt is absolute position in list. Jump over found item.
# to set up for the next call to smartparse
@ sp.cnt = sp.cnt + sp.tmp
# parsekey delete_previous_word
delword
type $word(${sp.tmp - 1} $sp.list)
type ${[ ]}
}
{
# nothing found.. drop out of loop
# for this condidtion to occur we must be at the beginning
# of the loop... either first pass.. or just looped back
if (!sp.cnt && !sp.tmp)
{
# notfound condition set for return value later
@ sp.notfound = [$sp.cnt ,$sp.pat]
@ sp.run = 0
# echo *** smartparse: no matching pattern
}
# loop back
@ sp.cnt = 0
}
}
^assign -sp.tmp
if (!sp.list) {@sp.cnt = 0}
^assign -sp.list
if (sp.notfound == [])
{@ function_return = [$sp.cnt :$sp.pat]}
{@ function_return = sp.notfound;^assign -sp.notfound}
}
{
# echo *** sp NULL
# echo *** $2: $($2)
@ function_return = [$sp.cnt .$sp.pat]
}
^assign -sp.run
}
# alias words.. usage $word(<begin> <end> <words>)
# words(0 2 zero one two three ... ) == 'zero one two' and so on
alias words {
@ function_return = [$(${[$0]+2}-${[$1] +2})]
}
# This is like DELETE_PREVIOUS_WORD except that it delets to the
# previous space which is much more useful than the current
# behavior of deleting to the previos non- [a-zA-Z0-9] char. :-?
alias delword {
parsekey erase_to_end_of_line
if ((dw.char = right(1 $L)) != [ ]) {@ dw.nw = 0} {@dw.nw = 1}
while (((dw.char != [ ]) || dw.nw) && (dw.char != []))
{
parsekey backspace
if ((dw.char = right(1 $L)) != [ ]) {@ dw.nw = 0}
}
^assign -dw.char;^assign -dw.nw
}
# it is of course possible to do command completion with something like
alias expand.con parsekey erase_to_beg_of_line;type /connect $()
# /con<tab> expands to /connect
# Be careful though.. note the $() at the end of the line.
# Without this 'complete' sends expand.con /con and the above
# alias will add the '/con' back onto the end of the line resulting
# in /connect /con on the input line when you're done
# # # # # # # # # # MODULE WRITING PHILOSOPHY # # # # # # # # # #
# Some thoughts about using complete and designing complete modules.
#
# Basically for any given time you hit TAB there are three states
# normal, null, and nomatch
# normal - there is something on the command line to process
# and the command is in the command list maintained by 'complete'
# The associated command parser is called with the contents of the
# input line in it's entirety as the arguments.
# null - there is nothing at all on the command line and some
# default action must be taken. No parser need be called at all as well.
# nomatch - the command at the head of the input line is not
# found in the list of commands maintained by 'complete'.
# A default 'nomatch' parser may or may not be called but if it is called
# it's passed the entire contents of the input line.
#
# This is not the end of the story however.
# If you're writing a completion module of some sort there are the same
# 3 states plus 1 more. Let's say you want to write something to
# find a match for a given keyword prefix out of a list when you hit
# TAB. e.g. /eat ap<TAB> looks for matching words that start with ap
# The 4 actions are
# normal - There is a single match for ap and it expands /eat apple
# multiple matches - There is more than one match for ap and thus
# a choice must be made. Possible choices include
# 1. do nothing
# 2. list possible matches (like ^D) or set showmatch in tcsh shell
# *** matches for prefix 'ap': apple apricot apendage
# 3. match only the first occurance Currently what the /connect module
# does /eat apple
# 4. cycle through the possible matches for the keyword 'ap'.
# The 'testparse' modules uses this scheme and it's my favorite
# albiet a tad more expensive in terms of CPU cycles and responce
# time. (I'm sure someone could see the diff.. I can't ;)
# /eat ap<TAB> -> /eat apple<TAB> -> /eat apricot<TAB> etc..
# 5. display worthless error message
# *** non-unique matches found
# nomatch - as as before, nomatching keywords are found, the choices are
# limited to things like displaying the whole list or just cycling through
# to the next item in the list like the 'tabkey' script's 'messparse' does.
# null - This one is more likely to happen only if 'complete' saw the
# input line as null, but then the null action is ussually special anyway.
# Otherwise this may occur when you say just /eat<TAB> and the obvious
# thing to do here is just to display the list of items to choose from
# in an appropriate format.
# Just remember.. the parsing routine can really do anything it wants..
# it could simply 'sendline' the line on to the server and push a
# button to start WWIII when you hit tab.. It doesn't have to mess with the
# command line but it's more useful that way. Although.. you could write
# a tab completion module that when tab was hit.. it spell checked
# the line.. anything is possible..